package com.ruoyi.crm.service.impl;

import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.service.IService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dingtalk.api.request.OapiMessageCorpconversationAsyncsendV2Request;
import com.dingtalk.api.request.OapiRobotSendRequest;
import com.ruoyi.common.config.DDConstant;
import com.ruoyi.common.constant.CrmConstant;
import com.ruoyi.common.enums.AuditStatus;
import com.ruoyi.common.enums.erp.CrmOrderProgessEnum;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.dd.MessageUtil;
import com.ruoyi.common.utils.flow.FlowParamsUtils;
import com.ruoyi.crm.domain.*;
import com.ruoyi.crm.domain.dto.CrmOrderDTO;
import com.ruoyi.crm.mapper.CrmCustomerMapper;
import com.ruoyi.crm.mapper.CrmProductMapper;
import com.ruoyi.crm.service.*;
import com.taobao.api.ApiException;
import com.warm.flow.core.dto.FlowParams;
import com.warm.flow.core.enums.SkipType;
import org.checkerframework.checker.units.qual.C;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.crm.mapper.CrmOrderMapper;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

/**
 * 商机Service业务层处理
 *
 * @author yanwenliang
 * @date 2024-10-23
 */
@Service
public class CrmOrderServiceImpl extends ServiceImpl<CrmOrderMapper, CrmOrder> implements ICrmOrderService {
    @Autowired
    private CrmOrderMapper crmOrderMapper;

    @Autowired
    private CrmCustomerMapper crmCustomerMapper;

    @Autowired
    private ICrmOrderProductDiscountService crmOrderProductDiscountService;

    @Autowired
    private ICrmProductService crmProductService;

    @Autowired
    private ICrmOrderRegisterService crmOrderRegisterService;

    @Autowired
    private ICrmContractService crmContractService;

    @Autowired
    private ICrmAcceptanceSheetService crmAcceptanceSheetService;

    @Autowired
    private ICrmClearAccountService crmClearAccountService;

    /**
     * 查询商机
     *
     * @param orderId 商机主键
     * @return 商机
     */
    @Override
    public CrmOrder selectCrmOrderByOrderId(String orderId) {
        return crmOrderMapper.selectCrmOrderByOrderId(orderId);
    }

    /**
     * 查询商机列表
     *
     * @param crmOrder 商机
     * @return 商机
     */
    @Override
    public List<CrmOrder> selectCrmOrderList(CrmOrder crmOrder) {
        if (!SecurityUtils.hasAdmin()){
            crmOrder.setCreateBy(SecurityUtils.getUsername());
            // 小组成员可以看到自己小组的数据
            crmOrder.setOrderAscription("2");

            crmOrder.setGroupId(SecurityUtils.getLoginUser().getUser().getGroupId());
        }
        return crmOrderMapper.selectCrmOrderList(crmOrder);
    }

    /**
     * 新增商机
     *
     * @param crmOrder 商机
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int insertCrmOrder(CrmOrder crmOrder) throws ApiException, UnsupportedEncodingException, NoSuchAlgorithmException, InvalidKeyException {

        this.verifyOrderProgess(crmOrder);

        crmOrder.setCreateTime(DateUtils.getNowDate());
        crmOrder.setCreateBy(SecurityUtils.getUsername());
        crmOrder.setOrderId(IdWorker.getIdStr());
        crmOrder.setUserId(SecurityUtils.getUserId());

        List<CrmOrder> orderList = baseMapper.selectList(new LambdaQueryWrapper<CrmOrder>()
                .eq(CrmOrder::getCustomerId, crmOrder.getCustomerId())
                .eq(CrmOrder::getOrderName, crmOrder.getOrderName()));

        if (orderList.size() > 0) {
            throw new ServiceException("当前客户下已存在名为" + crmOrder.getOrderName() + "的商机，请前往 续费管理 中添加该商机续费情况");
        }

        // 设置续费信息
        if (!StringUtils.isEmpty(crmOrder.getParentOrderId())){
            CrmOrder order = new CrmOrder();
            order.setOrderId(crmOrder.getParentOrderId());
            order.setIsRenewal("1");
            this.setRenewal(order);
        }

        int i = crmOrderMapper.insertCrmOrder(crmOrder);

        if (i > 0) {
            this.submitProductDiscount(crmOrder);


           // 发送工作通知
            if (StringUtils.isNotEmpty(crmOrder.getHelpPerson()) && i > 0) {
                OapiMessageCorpconversationAsyncsendV2Request.Msg msg = new OapiMessageCorpconversationAsyncsendV2Request.Msg();
                msg.setMsgtype("markdown");
                msg.setMarkdown(new OapiMessageCorpconversationAsyncsendV2Request.Markdown());
                msg.getMarkdown().setTitle(crmOrder.getCreateBy() + "创建了协同商机");
                msg.getMarkdown().setText(crmOrder.getCreateBy() + "创建了协同商机(" + crmOrder.getOrderName() + ")" + "[立即查看](" + DDConstant.DD_FRONT_URL + DDConstant.FRONT_URL_HOST + "crm/order" + ")");
                MessageUtil.send(crmOrder.getHelpPerson(), msg);
            }

            // 发送群通知
            CrmCustomer crmCustomer = crmCustomerMapper.selectById(crmOrder.getCustomerId());
            crmOrder.setCustomerName(crmCustomer.getCustomerName());
            OapiRobotSendRequest.Markdown msg = this.createMsg(crmOrder, "项目新建通知");
            MessageUtil.sendGroup(msg, DDConstant.SECRET_INFO, DDConstant.CUSTOM_ROBOT_TOKEN_INFO);
        }
        return i;
    }

    /**
     * 创建产品折扣信息，以及发起审批流程
     * <p>
     * 1、先判断是否存在折扣信息
     * 2、计算折扣率
     * 3、新增折扣申请的时候，判断是不是第一次申请，是则正常开启流程
     * 4、不是则删除原来流程，在开启新的流程
     * 5、判断当前订单是不是提交状态，是提交状态则将折扣申请的审批状态改为待审核，并开启下一流程
     *
     * @param crmOrder
     */
    private void submitProductDiscount(CrmOrder crmOrder) {
        // 创建产品折扣
        CrmOrderProductDiscount crmOrderProductDiscount = crmOrder.getCrmOrderProductDiscount();
        if (ObjectUtils.isEmpty(crmOrderProductDiscount)) {
            return;
        }

        // 如果是不申请折扣，则直接删除流程,或者跳过新增折扣流程
        if ("1".equals(crmOrder.getIsDiscount())) {
            CrmOrderProductDiscount discount = crmOrderProductDiscountService.getOne(new LambdaQueryWrapper<CrmOrderProductDiscount>()
                    .eq(CrmOrderProductDiscount::getUserId, SecurityUtils.getUserId())
                    .eq(CrmOrderProductDiscount::getOrderId, crmOrderProductDiscount.getOrderId()));

            if (!ObjectUtils.isEmpty(discount)) {
                FlowParamsUtils.remove(discount.getInstanceId());
                crmOrderProductDiscountService.removeById(discount.getDiscountId());
            }
            return;
        }

        crmOrderProductDiscount.setOrderId(crmOrder.getOrderId());
        crmOrderProductDiscount.setProductId(crmOrder.getProductId());
        CrmProduct crmProduct = crmProductService.getById(crmOrder.getProductId());

        if (ObjectUtils.isEmpty(crmProduct)) {
            throw new ServiceException("产品不存在，请刷新后重试！");
        }

        // 折扣后的价格
        BigDecimal discountPrice = crmOrderProductDiscount.getDiscountPrice();

        BigDecimal shippingPrice = crmProduct.getShippingPrice();

        // 判断是否有有效的价格数据
        if (ObjectUtils.isEmpty(discountPrice) || ObjectUtils.isEmpty(shippingPrice) || shippingPrice.compareTo(BigDecimal.ZERO) < 0) {
            throw new ServiceException("无效的价格数据，无法计算折扣率");
        }

        // 计算折扣率
        BigDecimal percentage = discountPrice.divide(shippingPrice, 2, BigDecimal.ROUND_HALF_UP);

        crmOrderProductDiscount.setDiscountRate(percentage);

        crmOrderProductDiscountService.insertCrmOrderProductDiscount(crmOrderProductDiscount);

        // 如果商机直接提交，则费用折扣申请的工作流程直接进入审批状态
        if ("1".equals(crmOrder.getStatus())) {
            crmOrderProductDiscountService.submit(crmOrderProductDiscount);
        }

    }

    /**
     * todo 检验项目进度
     *
     * @param crmOrder
     * @return
     */
    private boolean verifyOrderProgess(CrmOrder crmOrder) {
        String orderId = crmOrder.getOrderId();
        int count = 0;
        switch (crmOrder.getProgess()) {
            case "4":
                count = crmOrderRegisterService.count(new LambdaQueryWrapper<CrmOrderRegister>().eq(CrmOrderRegister::getOrderId, orderId));
                if (count == 0) throw new ServiceException("请完善项目立项表");
                break;
            case "5":
                count = crmContractService.count(new LambdaQueryWrapper<CrmContract>().eq(CrmContract::getOrderId, orderId));
                if (count == 0) throw new ServiceException("请完善项目合同表");
                break;
            case "6":
                crmAcceptanceSheetService.count(new LambdaQueryWrapper<CrmAcceptanceSheet>().eq(CrmAcceptanceSheet::getOrderId, orderId));
                if (count == 0) throw new ServiceException("请完善项目验收表");
                break;
            case "7":
                crmClearAccountService.count(new LambdaQueryWrapper<CrmClearAccount>().eq(CrmClearAccount::getOrderId, orderId));
                if (count == 0) throw new ServiceException("请完善项目结算表");
                break;
        }
        return true;
    }

    /**
     * 组装群消息
     *
     * @param crmOrder
     * @return
     */
    private OapiRobotSendRequest.Markdown createMsg(CrmOrder crmOrder, String title) {
        OapiRobotSendRequest.Markdown markdown = new OapiRobotSendRequest.Markdown();
        markdown.setTitle(title);
        StringBuilder text = new StringBuilder();
        text.append("## **" + title + "**");
        text.append("  \n  ");
        text.append("项目名称：" + crmOrder.getOrderName());
        text.append("  \n  ");
        text.append("客户名称：" + crmOrder.getCustomerName());
        text.append("  \n  ");
        text.append("项目金额：" + crmOrder.getPlanAmount());
        text.append("  \n  ");
        text.append("项目进度：" + CrmOrderProgessEnum.getInfo(crmOrder.getProgess()));
        text.append("  \n  ");
        text.append("负责人：" + crmOrder.getCreateBy());
        markdown.setText(text.toString());

        return markdown;
    }

    /**
     * 修改商机
     *
     * @param crmOrder 商机
     * @return 结果
     */
    @Override
    public int updateCrmOrderInfo(CrmOrder crmOrder)  {
        crmOrder.setUpdateTime(DateUtils.getNowDate());
        crmOrder.setUpdateBy(SecurityUtils.getUsername());

        int i = crmOrderMapper.updateCrmOrder(crmOrder);

        if (i > 0) {
            //  发送群通知
            CrmCustomer crmCustomer = crmCustomerMapper.selectById(crmOrder.getCustomerId());
            crmOrder.setCustomerName(crmCustomer.getCustomerName());
            OapiRobotSendRequest.Markdown msg = this.createMsg(crmOrder, "项目变更通知");
            MessageUtil.sendGroup(msg, DDConstant.SECRET_INFO, DDConstant.CUSTOM_ROBOT_TOKEN_INFO);
        }

        return i;
    }

    /**
     * 修改商机
     *
     * @param crmOrder 商机
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updateCrmOrder(CrmOrder crmOrder) {

        this.verifyOrderProgess(crmOrder);

        CrmOrder order = baseMapper.selectById(crmOrder.getOrderId());

        if (ObjectUtils.isEmpty(order)) {
            throw new ServiceException("商机不存在，请刷新后重试！");
        }

        // 修改商机时，判断该是不是由暂存状态转换为提交状态的数据
        // 如果是，则提交发起产品折扣审批流程
        // 判断订单状态，符合条件则提交折扣
        if ("0".equals(order.getStatus()) && "1".equals(crmOrder.getStatus())) {
            this.submitProductDiscount(crmOrder);
        }

        // 获取用户折扣信息
        CrmOrderProductDiscount discount = crmOrderProductDiscountService.getOne(
                new LambdaQueryWrapper<CrmOrderProductDiscount>()
                        .eq(CrmOrderProductDiscount::getUserId, SecurityUtils.getUserId())
                        .eq(CrmOrderProductDiscount::getOrderId, crmOrder.getOrderId())
        );

        // 取出折扣价格
        BigDecimal discountPrice = discount != null ? discount.getDiscountPrice() : null;
        CrmOrderProductDiscount crmOrderProductDiscount = crmOrder.getCrmOrderProductDiscount();
        BigDecimal price = crmOrderProductDiscount != null ? crmOrderProductDiscount.getDiscountPrice() : null;

        // 将前端传来的金额格式话，防止equals比较失败
        BigDecimal discountPriceNormalized = discountPrice != null ? discountPrice.setScale(2, RoundingMode.HALF_UP) : null;
        BigDecimal priceNormalized = price != null ? price.setScale(2, RoundingMode.HALF_UP) : null;

        // 如果原折扣申请为空，新折扣申请不为空，表示折扣信息发生变化，执行变更
        // 如果原折扣申请不为空，新折扣申请为空，表示折扣信息发生变化，执行变更
        // 如果新老折扣金额不相同，也执行变更
        if ((discount == null && crmOrderProductDiscount != null) ||
                (discount != null && crmOrderProductDiscount == null) ||
                (discount != null && crmOrderProductDiscount != null && !discountPriceNormalized.equals(priceNormalized))) {
            this.submitProductDiscount(crmOrder);
        }


        return this.updateCrmOrderInfo(crmOrder);
    }

    /**
     * 批量删除商机
     *
     * @param orderIds 需要删除的商机主键
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int deleteCrmOrderByOrderIds(String[] orderIds) {

        List<CrmOrder> list = baseMapper.selectBatchIds(Arrays.asList(orderIds));

        List<Long> instanceIds = new ArrayList<>();

        list.forEach(crmOrder -> {
            CrmOrderProductDiscount discount = crmOrderProductDiscountService.getOne(
                    new LambdaQueryWrapper<CrmOrderProductDiscount>()
                            .eq(CrmOrderProductDiscount::getUserId, crmOrder.getUserId())
                            .eq(CrmOrderProductDiscount::getOrderId, crmOrder.getOrderId())
                            .eq(CrmOrderProductDiscount::getProductId, crmOrder.getProductId()));

            if (!ObjectUtils.isEmpty(discount)) {
                instanceIds.add(discount.getInstanceId());
                crmOrderProductDiscountService.removeById(discount.getDiscountId());
            }
        });

        if (instanceIds.size() > 0) {
            FlowParamsUtils.remove(instanceIds);
        }

        return crmOrderMapper.deleteCrmOrderByOrderIds(orderIds);
    }

    /**
     * 删除商机信息
     *
     * @param orderId 商机主键
     * @return 结果
     */
    @Override
    public int deleteCrmOrderByOrderId(String orderId) {
        return crmOrderMapper.deleteCrmOrderByOrderId(orderId);
    }

    /**
     * 获取订单信息
     *
     * @param crmCustomerId
     * @return
     */
    @Override
    public List<CrmOrderDTO> getCrmOrderDTO(String crmCustomerId) {
        return crmOrderMapper.getCrmOrderDTO(crmCustomerId);
    }

    /**
     * 获取订单信息
     *
     * @param crmOrder
     * @return
     */
    @Override
    public CrmOrder getOrderOne(CrmOrder crmOrder) {
        return crmOrderMapper.getOrderOne(crmOrder);
    }

    @Override
    public Boolean setRenewal(CrmOrder crmOrder) {
        int update = crmOrderMapper.update(crmOrder, new LambdaUpdateWrapper<CrmOrder>()
                .eq(CrmOrder::getOrderId, crmOrder.getOrderId())
                .set(CrmOrder::getIsRenewal, crmOrder.getIsRenewal()));
        return update > 0;
    }
}
